-- Frame Generation --

Frame.Derive (.tree => .tree1) :-
	Frame.Declarations (.tree => .tree1) #

Frame.Declarations
	(.decls, .remains => .decls1, .remains1) :-
	Frame.Declaration (.decls => .decls1),
	Frame.Declarations (.remains => .remains1) #
Frame.Declarations ($ => $) #

Frame.Declaration (TYPEDEF .type .name => TYPEDEF .type1 .name) :-
	Frame.Type (.type => .type1) #
Frame.Declaration (VARDEF .type .name => VARDEF .type1 .name) :-
	Frame.Type (.type => .type1) #
Frame.Declaration (VARDEFVALUE .type .name .value =>
	VARDEFVALUE .type1 .name .value) :-
	Frame.Type (.type => .type1) #

Frame.Type (VOID => VOID) #
Frame.Type (INTTYPE .i => INTTYPE .i) #
Frame.Type (PTR .i => PTR .i1) :- Frame.Type (.i => .i1) #
Frame.Type (ARRAY .size .i => ARRAY .size .i1) :- Frame.Type (.i => .i1) #
Frame.Type (CLASS .decls => CLASS .decls1) :-
	Frame.Declarations (.decls => .decls1) #
Frame.Type (FUNC .parms .return .block => FUNC .parms1 .return1 .block1) :-
	Frame.Declarations (.parms => .parms1),
	Frame.Type (.return => .return1),
	Frame.Function (.parms .block => .parms .block1) #
Frame.Type (TYPENAME .name => TYPENAME .name) #

	-- Convert (VAR ???) to storage tags (FRAMED xxx)
Frame.Function (.parms .block => .parms .block1) :-
	ExtractLocals.Statements .locals .block,
	Frame.AssignParameters .parms .parmStores (0 => .),
	Frame.AssignLocals .locals .localStores (0 => .),
	list.append .parmStores .localStores .varStores,
	ReplaceLocals.Statements .varStores (.block => .block1) #
--	Frame.ReplaceVariables .varStores (.block => .block1) #

Frame.AssignParameters $ $ (.parmSize => .parmSize) #
Frame.AssignParameters (VARDEF .type .var, .remains)
	(TYPE.VAR.STORE .type .var (FRAMED .offset), .infos)
	(.parmSize0 => .parmSize1) :-
	Type.Size .type .size,
	let .parmSize (.parmSize0 + .size),
	Frame.AssignParameters .remains .infos (.parmSize => .parmSize1),
	let .offset (.parmSize1 - .parmSize0) #

Frame.AssignLocals (VARDEF .type .var, .vars)
	(TYPE.VAR.STORE .type .var (FRAMED .frame1), .infos)
	(.frame => .frameSize) :-
	Type.Size .type .size,
	let .frame1 (.frame - .size),
	Frame.AssignLocals .vars .infos (.frame1 => .frameSize) #
Frame.AssignLocals $ $ (.frameSize => .frameSize) #

Frame.ReplaceVariables $ (.func => .func) #
Frame.ReplaceVariables (TYPE.VAR.STORE . .var .store, .infos1)
	(.func0 => .func1) :-
	Replace .func0 (VAR .var) .store .func,
	Frame.ReplaceVariables .infos1 (.func => .func1) #

ExtractLocals.Statements .locals (.stmt, .remains) :-
	ExtractLocals.Statement .e1 .stmt,
	ExtractLocals.Statements .e2 .remains,
	list.append .e1 .e2 .locals #
ExtractLocals.Statements () $ #

ExtractLocals.Statement .locals (BLOCK .stmts) :-
	ExtractLocals.Statements .locals .stmts #
ExtractLocals.Statement (VARDEF .type .name,) (VARDEF .type .name) #
ExtractLocals.Statement () (TYPEDEF . .) #
ExtractLocals.Statement () . #
ExtractLocals.Statement $ . #

ReplaceLocals.Statements .stores (.stmt, .remains => .stmt1, .remains1) :-
	ReplaceLocals.Statement .stores (.stmt => .stmt1),
	ReplaceLocals.Statements .stores (.remains => .remains1) #
ReplaceLocals.Statements . ($ => $) #

ReplaceLocals.Statement .stores (BLOCK .stmts => BLOCK .stmts1) :-
	ReplaceLocals.Statements .stores (.stmts => .stmts1) #
ReplaceLocals.Statement . (VARDEF .type .name => VARDEF .type .name) #
ReplaceLocals.Statement . (TYPEDEF .type .name => TYPEDEF .type .name) #
ReplaceLocals.Statement .stores (IF .cond .then => IF .cond1 .then1) :-
	ReplaceLocals.Expression .stores (.cond => .cond1),
	ReplaceLocals.Statement .stores (.then => .then1) #
ReplaceLocals.Statement .stores
	(IFELSE .cond .then .else =>IFELSE .cond1 .then1 .else1) :-
	ReplaceLocals.Expression .stores (.cond => .cond1),
	ReplaceLocals.Statement .stores (.then => .then1),
	ReplaceLocals.Statement .stores (.else => .else1) #
ReplaceLocals.Statement .stores (WHILE .cond .do => WHILE .cond1 .do1) :-
	ReplaceLocals.Expression .stores (.cond => .cond1),
	ReplaceLocals.Statement .stores (.do => .do1) #
ReplaceLocals.Statement .stores (EXPR .e => EXPR .e1) :-
	ReplaceLocals.Expression .stores (.e => .e1) #

ReplaceLocals.Expression .env (CALL .func .parms => CALL .func1 .parms1) :-
	ReplaceLocals.Expression .env (.func => .func1),
	ReplaceLocals.Parameters .env (.parms => .parms1) #

ReplaceLocals.Parameters . ($ => $) #
ReplaceLocals.Parameters .env (.var, .remains => .var1, .remains1) :-
	ReplaceLocals.Expression .env (.var => .var1),
	ReplaceLocals.Parameters .env (.remains => .remains1) #

ReplaceLocals.Expression .stores (ASGop .l .r => ASGop .l1 .r1) :-
	ReplaceLocals.Expression .stores (.l => .l1),
	ReplaceLocals.Expression .stores (.r => .r1) #
ReplaceLocals.Expression .stores (ADDop .l .r => ADDop .l1 .r1) :-
	ReplaceLocals.Expression .stores (.l => .l1),
	ReplaceLocals.Expression .stores (.r => .r1) #
ReplaceLocals.Expression .stores (SUBop .l .r => SUBop .l1 .r1) :-
	ReplaceLocals.Expression .stores (.l => .l1),
	ReplaceLocals.Expression .stores (.r => .r1) #
ReplaceLocals.Expression .stores (MULop .l .r => MULop .l1 .r1) :-
	ReplaceLocals.Expression .stores (.l => .l1),
	ReplaceLocals.Expression .stores (.r => .r1) #
ReplaceLocals.Expression .stores (DIVop .l .r => DIVop .l1 .r1) :-
	ReplaceLocals.Expression .stores (.l => .l1),
	ReplaceLocals.Expression .stores (.r => .r1) #

ReplaceLocals.Expression .stores (MEMBER .v .field => MEMBER .v1 .field) :-
	ReplaceLocals.Expression .stores (.v => .v1) #

ReplaceLocals.Expression .stores (VAR .var => .store) :-
	list.member .stores (TYPE.VAR.STORE . .var .store) ! #
ReplaceLocals.Expression . (.e => .e) #
